package dao

import (
	"192.168.1.75/go-pkg/logx"
	"context"
	"errors"
	"gorm.io/gorm"
	"mini-app/internal/models"
)

type OnlineEventUser struct{}

// Create 新增活动参与用户
func (OnlineEventUser) Create(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	userID string,
	openid string,
	status int,
	usedPoints int64,
	userAddress models.UserAddress,
	outTradeNo string,
) (success bool) {
	rowsAffected := db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Create(&models.OnlineEventUser{
			OnlineEventID: onlineEventID,
			UserID:        userID,
			OpenID:        openid,
			Status:        status,
			Used_Points:   usedPoints,
			UserName:      userAddress.UserName,
			TelNumber:     userAddress.TelNumber,
			PostalCode:    userAddress.PostalCode,
			ProvinceName:  userAddress.ProvinceName,
			CityName:      userAddress.CityName,
			CountyName:    userAddress.CountyName,
			StreetName:    userAddress.StreetName,
			DetailAddress: userAddress.DetailAddress,
			OutTradeNo:    outTradeNo,
		}).RowsAffected
	return rowsAffected > 0
}

// List 活动参与用户列表
func (t OnlineEventUser) List(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	status int, /*0-已参与 1-申请成功 2-中奖 3-未中奖*/
	fields []string,
	selectedUserIds *[]string,
	selectedPuppetUserIds *[]string,
	isPuppetUser *bool,
	page, limit int,
) (list []models.OnlineEventUser, total int64, err error) {
	tx := db.WithContext(ctx).
		Model(&models.OnlineEventUser{}).
		Where("online_event_id = ?", onlineEventID)

	if status > 0 {
		tx = tx.Where("status = ?", status)
	}

	if limit > 0 {
		if limit > 2000 {
			limit = 2000
		}
		tx = tx.Limit(limit)
	}
	if page > 0 && limit > 0 {
		tx = tx.Offset((page - 1) * limit)
	}
	if len(fields) > 0 {
		tx = tx.Select(fields)
	}

	{
		// selectedUserIds或selectedPuppetUserIds为nil，代表不作为筛选条件
		//如果selectedUserIds或selectedPuppetUserIds作为筛选条件，
		//user_id要在这两个id列表中，如果这两个列表为空，则不会有user_id满足条件，则会返回空列表
		if selectedUserIds != nil || selectedPuppetUserIds != nil {
			var conditions *gorm.DB = db.Where("1 != 1")
			if selectedUserIds != nil {
				conditions = conditions.Or("user_id IN ?", *selectedUserIds)
			}

			if selectedPuppetUserIds != nil {
				conditions = conditions.Or("user_id IN ?", *selectedPuppetUserIds)
			}

			tx = tx.Where(conditions)
		}

	}

	if isPuppetUser != nil {
		tx = tx.Where("is_puppet_user = ?", *isPuppetUser)
	}

	err = tx.Find(&list).Error
	if err != nil {
		logx.Error(ctx, "OnlineEventUser.List", logx.Any("err", err))
		return nil, total, err
	}
	tx.Count(&total)

	return list, total, nil
}

// Count 活动参与用户统计
func (OnlineEventUser) Count(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	status int,
) (total int64) {
	tx := db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Where("online_event_id = ?", onlineEventID)
	if status > 0 {
		tx = tx.Where("status = ?", status)
	}
	tx.Count(&total)
	return
}

// Detail 活动参与用户详情
func (OnlineEventUser) Detail(
	ctx context.Context,
	db *gorm.DB,
	ID string,
	openID string,
	onlineEventID string,
) *models.OnlineEventUser {
	var record models.OnlineEventUser
	tx := db.WithContext(ctx).Model(&models.OnlineEventUser{})
	if ID != "" {
		tx = tx.Where("id = ?", ID)
	}
	if openID != "" {
		tx = tx.Where("openid = ? AND online_event_id = ?", openID, onlineEventID)
	}
	rowsAffected := tx.Take(&record).RowsAffected
	if rowsAffected == 1 {
		return &record
	}
	return nil
}

// AddSupports 增加助力人数
func (OnlineEventUser) AddSupports(
	ctx context.Context,
	db *gorm.DB,
	supportID string,
) {
	db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Where("id = ?", supportID).
		Update("current_supporters", gorm.Expr("current_supporters + 1"))
}

func (OnlineEventUser) SetWinner(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	userIDs []string,
	isPuppetUser bool,
) error {

	err := db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Where("online_event_id = ?", onlineEventID).
		Where("user_id IN ?", userIDs).
		Where("is_puppet_user", isPuppetUser).
		Update("status", 2).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
		logx.Error(ctx, "OnlineEventUser.SetWinner", logx.Any("err", err))
		return err
	}

	return nil
}

func (OnlineEventUser) SetWinnerByIds(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	IDs []string,
) error {
	err := db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Where("online_event_id = ?", onlineEventID).
		Where("id IN ?", IDs).
		Update("status", 2).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil
		}
		logx.Error(ctx, "OnlineEventUser.SetWinnerByIds", logx.Any("err", err))
		return err
	}

	return nil
}

func (OnlineEventUser) SetApplySuccess(
	ctx context.Context,
	db *gorm.DB,
	JoinID string,
) error {
	return db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Where("id = ?", JoinID).
		Where("status = 0").
		Update("status", 1).Error
}

func (OnlineEventUser) WinCount(
	ctx context.Context,
	db *gorm.DB,
	userID string,
) int64 {
	var count int64
	db.WithContext(ctx).Model(&models.OnlineEventUser{}).
		Where("user_id = ?", userID).
		Where("status = ?", 2).
		Count(&count)
	return count
}

// FirstOrCreate 查找或创建活动参与用户
func (OnlineEventUser) FirstOrCreate(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	userID string,
	openid string,
	status int,
	usedPoints int64,
	userAddress models.UserAddress,
	outTradeNo string,
	isPuppetUser bool,
) (*models.OnlineEventUser, error) {
	var record models.OnlineEventUser
	err := db.WithContext(ctx).Where(&models.OnlineEventUser{
		OnlineEventID: onlineEventID,
		UserID:        userID,
		IsPuppetUser:  isPuppetUser,
	}).FirstOrCreate(&record, &models.OnlineEventUser{
		OnlineEventID: onlineEventID,
		UserID:        userID,
		OpenID:        openid,
		Status:        status,
		Used_Points:   usedPoints,
		UserName:      userAddress.UserName,
		TelNumber:     userAddress.TelNumber,
		PostalCode:    userAddress.PostalCode,
		ProvinceName:  userAddress.ProvinceName,
		CityName:      userAddress.CityName,
		CountyName:    userAddress.CountyName,
		StreetName:    userAddress.StreetName,
		DetailAddress: userAddress.DetailAddress,
		OutTradeNo:    outTradeNo,
		IsPuppetUser:  isPuppetUser,
	}).Error
	return &record, err
}

// Delete 删除活动参与用户
func (OnlineEventUser) Delete(
	ctx context.Context,
	db *gorm.DB,
	onlineEventID string,
	userID string,
	IsPuppetUser bool,
) error {
	return db.WithContext(ctx).Where(&models.OnlineEventUser{
		OnlineEventID: onlineEventID,
		UserID:        userID,
		IsPuppetUser:  IsPuppetUser,
	}).Delete(&models.OnlineEventUser{}).Error
}
